package com.zg.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.management.OperatingSystemMXBean;
import com.zg.CliemtManage.ClientInfo;
import com.zg.domain.DataForClient;
import com.zg.domain.LotClient;
import com.zg.domain.dto.ClientInfoDto;
import com.zg.domain.vo.ClientPasswordVo;
import com.zg.domain.vo.LotClientVo;
import com.zg.domain.vo.SysInfoVo;
import com.zg.exception.Result;
import com.zg.service.MqttBrokerAdminService;
import io.netty.channel.Channel;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service("brokerAdmin")
public class MqttBrokerAdminSerImpl implements MqttBrokerAdminService {


    private ClientInfo clientInfoService = new ClientInfo();

    @Override
    public List getOnlineClient() {
        ConcurrentHashMap<Channel,String> onlineMap = DataForClient.getOnlineMap();
        ConcurrentHashMap<String, LotClient> clientDetail = DataForClient.getClientDetail();
        List list= new ArrayList<>();
        onlineMap.forEach((key,value)->{
            ClientInfoDto clientInfoDto = new ClientInfoDto();
            String client_id = onlineMap.get(key);
            LotClient lotClient = clientDetail.get(client_id);
            clientInfoDto.setClient_id(client_id);
            clientInfoDto.setIp(key.remoteAddress().toString());
            clientInfoDto.setTopic(lotClient.getTopics());
            list.add(clientInfoDto);
        });
        return list;
    }

    @Override
    public void delClient(String client_id) {
        clientInfoService.admin_delOnlineClient(client_id);
    }

    @Override
    public void delClientTopic(String client_id, List<String> list) {
        clientInfoService.admin_delSubTopic(client_id,list);
    }

    @Override
    public Object addClientPassword(String user, String password) {
        ConcurrentHashMap<String, String> user_password = DataForClient.getUser_password();
        if (user_password.containsKey(user)){
            return Result.fail(500,"用户名存在");
        }
        user_password.put(user, password);
        return Result.success();
    }

    @Override
    public Object delClientPassword(String user) {
        ConcurrentHashMap<String, String> user_password = DataForClient.getUser_password();
        user_password.remove(user);
        return Result.success();
    }

    @Override
    public Object updateClientPassword(String user, String password) {
        DataForClient.getUser_password().put(user,password);
        return Result.success();
    }

    @Override
    public Object getAllUser() {
        ConcurrentHashMap<String, String> user_password = DataForClient.getUser_password();
        ArrayList<ClientPasswordVo> clientPasswordVos = new ArrayList<>();
        user_password.forEach((key,value)->{
            ClientPasswordVo clientPasswordVo = new ClientPasswordVo(key,value);
            clientPasswordVos.add(clientPasswordVo);
        });
        return clientPasswordVos;
    }

    @Override
    public Object getAllTopic() {
        ConcurrentHashMap<String, LotClient> clientDetail = DataForClient.getClientDetail();
        List<LotClientVo> lotClientVos = new ArrayList<>();
        clientDetail.forEach((key,value)->{
            for (String topic : value.getTopics()) {
                LotClientVo lotClientVo = new LotClientVo();
                lotClientVo.setClient_id(value.getClient_id());
                lotClientVo.setTopic(topic);
                lotClientVo.setIp(value.getChannel().toString());
                lotClientVos.add(lotClientVo);
            }
        });
        return lotClientVos;
    }

    @Override
    public Object getTotal() {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("onlineClient",DataForClient.getClientDetail().size());
        map.put("topic",DataForClient.getTopic_Client().size());
        return map;
    }

    @Override
    public Object getSysInfo() {
        int byteToMb = 1024 * 1024;
        OperatingSystemMXBean osBean = (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
        SysInfoVo sysInfoVo = new SysInfoVo();
        sysInfoVo.setTotalMemory(Runtime.getRuntime().totalMemory()/byteToMb);
        sysInfoVo.setFreeMemory(Runtime.getRuntime().freeMemory()/byteToMb);
        sysInfoVo.setMaxMemory(Runtime.getRuntime().maxMemory()/byteToMb);
        sysInfoVo.setUseMemory(sysInfoVo.getTotalMemory()- sysInfoVo.getFreeMemory());
        sysInfoVo.setPhysicalFree(osBean.getFreePhysicalMemorySize()/byteToMb);
        sysInfoVo.setPhysicalTotal(osBean.getTotalPhysicalMemorySize()/byteToMb);
        sysInfoVo.setOsName(System.getProperty("os.name"));
        sysInfoVo.setThreadNum(Runtime.getRuntime().availableProcessors());
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        sysInfoVo.setJvmName(runtimeMXBean.getVmName());
        sysInfoVo.setJdkVersion(System.getProperty("java.version"));
        sysInfoVo.setRunTime(toDuration(runtimeMXBean.getUptime()));
        sysInfoVo.setCpuUsed(osBean.getSystemLoadAverage()*100);
        return sysInfoVo;
    }

    @Override
    public void sendTopicMsg(String topic, String data) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("action","admin");
        map.put("data",data);
        map.put("time",System.currentTimeMillis());
        clientInfoService.relayMessage(topic, map);
    }

    @Override
    public void sendMsgToClient(String client_id, String topic, String data) {
        clientInfoService.sendMsgToClient(client_id,topic,data);
    }


    private String toDuration(double uptime) {
        NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
        NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
        uptime /= 1000;
        if (uptime < 60) {
            return fmtD.format(uptime) + " seconds";
        }
        uptime /= 60;
        if (uptime < 60) {
            long minutes = (long) uptime;
            String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
            return s;
        }
        uptime /= 60;
        if (uptime < 24) {
            long hours = (long) uptime;
            long minutes = (long) ((uptime - hours) * 60);
            String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
            if (minutes != 0) {
                s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
            }
            return s;
        }
        uptime /= 24;
        long days = (long) uptime;
        long hours = (long) ((uptime - days) * 24);
        String s = fmtI.format(days) + (days > 1 ? " days" : " day");
        if (hours != 0) {
            s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
        }
        return s;
    }
}
